home *** CD-ROM | disk | FTP | other *** search
- /* OS- and machine-dependent stuff for IBM-PC running MS-DOS and Turbo-C
- * Copyright 1991 Phil Karn, KA9Q
- * Mods by KO4KS
- */
- #include <stdio.h>
- #include <conio.h>
- #include <dir.h>
- #include <dos.h>
- #include <io.h>
- #ifdef UNIX
- #include <sys/types.h>
- #endif
- #include <sys/stat.h>
- #include <string.h>
- #include <process.h>
- #include <fcntl.h>
- #include <alloc.h>
- #include <stdarg.h>
- #include <bios.h>
- #include "global.h"
- #include "config.h"
- #include "mbuf.h"
- #include "proc.h"
- #include "iface.h"
- #include "internet.h"
- #include "session.h"
- #include "tty.h"
- #include "socket.h"
- #include "smtp.h"
- #include "cmdparse.h"
- #include "dirutil.h"
- #include "pc.h"
-
- #ifdef XSPAWN
- #include "xspawn.h"
- static int Xspawn = 1;
- #define SPAWNVP xspawnvp
- #else
- #define SPAWNVP spawnvp
- #endif
-
- #define CTLC 0x3
- #define DEL 0x7f
-
- static int kbchar __ARGS((void));
- extern int Curdisp;
- extern struct proc *Display;
- FILE *Rawterm;
- unsigned _stklen = 8192;
- volatile int Tick;
- static int32 Starttime;
- int32 Clock;
-
- #ifdef MULTITASK
- int Background = 0;
- int Nokeys = 0;
- extern unsigned Minheap;
- #endif
- extern int Tracesession;
-
- int Watchdog = 0; /* Watch Dog off by default */
- int WDTick = 300*(1000 / MSPTICK); /* 5 minutes watchdog timer */
- int WDCurr = 300*(1000 / MSPTICK); /* Initial count down timer */
-
- /* This flag is set by setirq() if IRQ 8-15 is used, indicating
- * that the machine is a PC/AT with a second 8259 interrupt controller.
- * If this flag is set, the interrupt return code in pcgen.asm will
- * send an End of Interrupt command to the second 8259 as well as the
- * first.
- */
- int Isat;
-
- static char Ttbuf[BUFSIZ];
- static char Tsbuf[BUFSIZ];
- static int saved_break;
-
- /* Keyboard input buffer */
- #define KBSIZE 256
- static struct {
- char buf[KBSIZE];
- char *wp;
- char *rp;
- int cnt;
- } Keyboard;
-
- int
- am_i_an_AT()
- {
- unsigned char *model_code = MK_FP(0xF000,0xFFFE);
-
- if(*model_code == 0xFC)
- return 1;
- else
- return 0;
- }
-
- /* Following code from Doug Crompton */
- /* define the error messages for trapping disk problems
- */
- static char *crit_err_msg[] = {
- "write protect",
- "unknown unit",
- "not ready",
- "unknown command",
- "data error (CRC)",
- "bad request",
- "seek error",
- "unknown media type",
- "sector not found",
- "printer out of paper",
- "write fault",
- "read fault",
- "general failure",
- "reserved",
- "reserved",
- "invalid disk change"
- };
-
-
- int
- errhandler(errval,ax,bp,si)
- int errval, ax, bp, si;
- {
- char msg[80];
- unsigned di;
- int drive;
- int errorno;
-
- di= _DI;
-
- #ifndef DOSX286
- if (ax < 0)
- hardretn(3);
- #endif
- drive = ax & 0x00FF;
- errorno = di & 0x00FF;
- sprintf(msg, "\r\nError: %s on drive %c\r\n$",
- crit_err_msg[errorno], 'A' + drive);
- bdosptr(0x09,msg,0);
- #ifndef DOSX286
- hardretn(3);
- #endif
- return 0; /* to please the compiler */
- }
-
-
- /* Called at startup time to set up console I/O, memory heap */
- void
- ioinit()
- {
- /* Fail all I/O errors */
- harderr(errhandler);
-
- /* Save these two file table entries for something more useful */
- fclose(stdaux);
- fclose(stdprn);
- setbuf(stdout,Tsbuf);
-
- Rawterm = fopen("con","wb");
- setbuf(Rawterm,Ttbuf);
- /* this breaks tab expansion so you must use ANSI or NANSI */
- ioctl(fileno(Rawterm), 1, (ioctl(fileno(Rawterm),0) & 0xff) | 0x20);
- saved_break = getcbrk();
- setcbrk(0);
-
- /* test to see if we're running on an AT class machine.
- * Set Isat flag accordingly - N1BEE
- */
- Isat = am_i_an_AT();
- Starttime = bioscnt();
- /* Link timer handler into timer interrupt chain */
- chtimer(btick);
-
- /* Find out what multitasker we're running under, if any */
- chktasker();
-
- /* Initialize keyboard queue */
- Keyboard.rp = Keyboard.wp = Keyboard.buf;
-
- }
- /* Called just before exiting to restore console state */
- void
- iostop()
- {
- struct iface *ifp,*iftmp;
- void (**fp)();
-
- setbuf(Rawterm,NULLCHAR);
- ioctl(fileno(Rawterm), 1, ioctl(fileno(Rawterm), 0) & 0xff & ~0x20);
- setcbrk(saved_break);
- for(ifp = Ifaces;ifp != NULLIF;ifp = iftmp){
- iftmp = ifp->next;
- if_detach(ifp);
- }
- /* Call list of shutdown functions */
- for(fp = Shutdown;*fp != NULLVFP;fp++){
- (**fp)();
- }
- }
- #ifdef SHELL
- /* Spawn subshell */
- int
- doshell(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- char *command;
- int ret;
-
- #ifdef MULTITASK
- if(Background) {
- if(!start_back())
- return -1;
- Nokeys++;
- }
- free(mallocw(Minheap)); /* Force heap/core break to reserve a heap */
- #endif
-
- if(argc == 1 || !stricmp(argv[1], "/c")) {
- if((command = getenv("COMSPEC")) == NULLCHAR)
- command = "COMMAND.COM";
- #ifdef XSPAWN
- if (!Xspawn)
- ret = spawnvp(P_WAIT,command,argv);
- else
- #endif
- ret = SPAWNVP(P_WAIT,command,argv);
- } else {
- #ifdef XSPAWN
- if (!Xspawn)
- ret = spawnvp(P_WAIT,argv[1],(argv + 1));
- else
- #endif
- ret = SPAWNVP(P_WAIT,argv[1],(argv + 1));
- }
-
- #ifdef MULTITASK
- if(Background) {
- Nokeys--;
- stop_back();
- }
- #endif
-
- return ret;
- }
- #endif
-
- #ifdef ALLCMD
- /* Spawn mailer as subshell */
- int
- dobmail(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- char *command;
- int ret;
-
- #ifdef MULTITASK
- if(Background) {
- if(!start_back())
- return -1;
- Nokeys++;
- }
- free(mallocw(Minheap));
- #endif
-
- if((command = getenv("MAILER")) == NULLCHAR)
- command = "BM.EXE";
- #ifdef XSPAWN
- if (!Xspawn)
- ret = spawnvp(P_WAIT,command,argv);
- else
- #endif
- ret = SPAWNVP(P_WAIT,command,argv);
-
- #ifdef MULTITASK
- if(Background) {
- Nokeys--;
- stop_back();
- }
- #endif
-
- smtptick(NULL); /* tickle smtp to send any mail */
- return ret;
- }
- #endif /*ALLCMD*/
-
- #ifdef MULTITASK
- /* if multitask mode is set - allow NOS and shell/mail to share system time */
- dobackg(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- return setbool(&Background,"Multitasking DOS Shell ",argc,argv);
- }
- #endif
-
- /* if watch-dog mode is set - make NOS reboot the system if it stalls */
- dowatchdog(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- return setbool(&Watchdog,"NOS Watch Dog",argc,argv);
- }
-
- #ifdef XSPAWN
- doxspawn(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- int retval;
-
- retval = setbool(&Xspawn,"XSPAWN mode",argc,argv);
- _swap = (Xspawn ^ 1);
- return retval;
- }
- #endif
-
- /* Keyboard interrupt handler */
- void
- kbint()
- {
- int sig = 0;
- int c;
-
- #ifdef MULTITASK
- if(Background && Nokeys)
- return;
- #endif
-
- while((c = kbraw()) != -1 && Keyboard.cnt < KBSIZE){
- sig = 1;
- *Keyboard.wp++ = c;
- if(Keyboard.wp == &Keyboard.buf[KBSIZE])
- Keyboard.wp = Keyboard.buf;
- Keyboard.cnt++;
- #ifdef SCREENSAVER
- sskick();
- #endif
- }
- if(sig){
- psignal(&Keyboard,0);
- }
- }
- static int
- kbchar()
- {
- char c;
- char i_state;
-
- #ifdef MULTITASK
- if(Background && Nokeys)
- return -1;
- #endif
-
- i_state = dirps();
- while(Keyboard.cnt == 0)
- pwait(&Keyboard);
- Keyboard.cnt--;
- restore(i_state);
- c = *Keyboard.rp++;
- if(Keyboard.rp == &Keyboard.buf[KBSIZE])
- Keyboard.rp = Keyboard.buf;
- return uchar(c);
- }
- /* Flush the raw terminal output */
- void
- rflush()
- {
- fflush(Rawterm);
- }
-
- #ifdef MSDOS
- #ifdef ALLCMD
- struct funcstr {
- unsigned char fkey;
- char alloced;
- char *fvalue;
- };
-
- struct funcstr DFAR fkeys[] = {
- 15,0,NULLCHAR, /* tab + shift */
- 59,1,NULLCHAR, /* F1 */
- 60,1,NULLCHAR, /* F2 */
- 61,1,NULLCHAR, /* F3 */
- 62,1,NULLCHAR, /* F4 */
- 63,0,NULLCHAR, /* F5 */
- 64,0,NULLCHAR, /* F6 */
- 65,0,NULLCHAR, /* F7 */
- 66,0,NULLCHAR, /* F8 */
- 67,0,NULLCHAR, /* F9 */
- 68,0,NULLCHAR, /* F10 */
- 71,1,NULLCHAR, /* home*/
- 72,1,"\033[A", /* up arrow*/
- 73,1,NULLCHAR, /* pgup */
- 75,1,"\033[D", /* left arrow */
- 77,1,"\033[C", /* right arrow */
- 79,1,NULLCHAR, /* end */
- 80,1,"\033[B", /* down arrow */
- 81,1,NULLCHAR, /* pgdn */
- 82,1,NULLCHAR, /* ins */
- 83,1,NULLCHAR, /* del */
- 84,0,NULLCHAR, /* F1 + shift*/
- 85,0,NULLCHAR, /* F2 + shift*/
- 86,0,NULLCHAR, /* F3 + shift*/
- 87,0,NULLCHAR, /* F4 + shift*/
- 88,0,NULLCHAR, /* F5 + shift*/
- 89,0,NULLCHAR, /* F6 + shift*/
- 90,0,NULLCHAR, /* F7 + shift*/
- 91,0,NULLCHAR, /* F8 + shift*/
- 92,0,NULLCHAR, /* F9 + shift*/
- 93,0,NULLCHAR, /* F10 + shift*/
- 94,0,NULLCHAR, /* F1 + control*/
- 95,0,NULLCHAR, /* F2 + control*/
- 96,0,NULLCHAR, /* F3 + control*/
- 97,0,NULLCHAR, /* F4 + control*/
- 98,0,NULLCHAR, /* F5 + control*/
- 99,0,NULLCHAR, /* F6 + control*/
- 100,0,NULLCHAR, /* F7 + control*/
- 101,0,NULLCHAR, /* F8 + control*/
- 102,0,NULLCHAR, /* F9 + control*/
- 103,0,NULLCHAR, /* F10 + control*/
- 104,0,NULLCHAR, /* F1 + alt*/
- 105,0,NULLCHAR, /* F2 + alt*/
- 106,0,NULLCHAR, /* F3 + alt*/
- 107,0,NULLCHAR, /* F4 + alt*/
- 108,0,NULLCHAR, /* F5 + alt*/
- 109,0,NULLCHAR, /* F6 + alt*/
- 110,0,NULLCHAR, /* F7 + alt*/
- 111,0,NULLCHAR, /* F8 + alt*/
- 112,0,NULLCHAR, /* F9 + alt*/
- 113,0,NULLCHAR, /* F10 + alt*/
- 114,0,NULLCHAR, /* PrtSc + ctl*/
- 117,0,NULLCHAR, /* end + ctl */
- 118,0,NULLCHAR, /* pgup + ctl */
- 119,0,NULLCHAR, /* home + ctl */
- 132,0,NULLCHAR, /* pgdn + ctl */
- 133,0,NULLCHAR, /* F11 */
- 134,0,NULLCHAR, /* F12 */
- 135,0,NULLCHAR, /* F11 + shift */
- 136,0,NULLCHAR, /* F12 + shift */
- 137,0,NULLCHAR, /* F11 + control */
- 138,0,NULLCHAR, /* F11 + control */
- 139,0,NULLCHAR, /* F11 + alt */
- 140,0,NULLCHAR, /* F11 + alt */
- 0,0,NULLCHAR
- };
-
- char Leftover = 0;
- char *Nextkey;
- #endif /*ALLCMD*/
- #endif /*MSDOS*/
-
- /* Read characters from the keyboard, translating them to "real" ASCII.
- * If none are ready, block. The F-10 key is special; translate it to -2.
- */
- #ifdef ALLCMD
- int
- kbread()
- {
- int c,i,j;
-
- if((c = Leftover) != 0) {
- Leftover = *Nextkey++;
- return c;
- }
- if((c = kbchar()) == 0){
- /* Lead-in to a special char */
- c = kbchar();
- switch(c){
- case 3: /* NULL (bizzare!) */
- c = 0;
- break;
- case 72: /* UP ARROW key (used as previous history command) */
- if(Current == Command) {
- c = UPARROW;
- break;
- }
- goto all;
- case 80: /* DOWN ARROW key (used as next history command) */
- if(Current == Command) {
- c = DNARROW;
- break;
- }
- goto all;
- case 68: /* F-10 key (used as command-mode escape) */
- if(fkeys[10].fvalue == NULLCHAR){
- c = -2;
- break;
- }
- goto all;
- case 82: /* INSERT key (used as status line toggle) */
- if(fkeys[19].fvalue == NULLCHAR){
- c = -105;
- break;
- }
- goto all;
- case 83: /* DELETE key (used as flow mode toggle) */
- if(fkeys[20].fvalue == NULLCHAR){
- c = -106;
- break;
- }
- goto all;
- case 71: /* HOME key (used to kick this session) */
- if(fkeys[11].fvalue == NULLCHAR){
- c = -107;
- break;
- }
- goto all;
- case 79: /* END key (used to kill this session) */
- if(fkeys[16].fvalue == NULLCHAR){
- c = -108;
- break;
- }
- goto all;
- case 73: /* PGUP key (used to toggle to previous session) */
- if(fkeys[13].fvalue == NULLCHAR){
- c = -109;
- break;
- }
- goto all;
- case 81: /* PGDN key (used to toggle to next session) */
- if(fkeys[18].fvalue == NULLCHAR){
- c = -110;
- break;
- }
- goto all;
- default: /* Dunno what it is */
- all:
- if(c > 58 && c < 68) { /* F1 to F9 */
- if(fkeys[c-58].fvalue == NULLCHAR) {
- c = (c - 56) * -1; /* NO fkey defined - WG7J */
- break;
- }
- }
- for(i=0;(j = fkeys[i].fkey) != 0;i++)
- if(j == c) {
- Nextkey = fkeys[i].fvalue;
- if(Nextkey == NULLCHAR) {
- c = -1;
- return c;
- }
- /* If first char of fvalue is '~'
- * switch to command session.
- */
- if((c = *Nextkey++) == '~') {
- c = -2;
- Leftover = *Nextkey++;
- } else {
- if(c != 0)
- Leftover = *Nextkey++;
- else
- c = -1;
- }
- return c;
- }
- c = -1;
- }
- }
- return c;
- }
- #else /*ALLCMD*/
-
- int
- kbread()
- {
- int c;
-
- if((c = kbchar()) == 0){
- /* Lead-in to a special char */
- c = kbchar();
- if(Current == Command) { /* Check for command recall */
- if(c == 72) /* UP arrow */
- return UPARROW;
- if(c == 80) /* DOWN arrow */
- return DNARROW;
- }
- switch(c){
- case 3: /* NULL (bizzare!) */
- c = 0;
- break;
- case 68: /* F-10 key (used as command-mode escape) */
- c = -2;
- break;
- case 83: /* DEL key */
- c = 0x7f;
- break;
- default: /* Dunno what it is */
- if(c > 58 && c < 68) /* F1 to F9 */
- c = (c - 56) * -1;
- else
- c = -1;
- }
- }
- return c;
- }
-
- #endif /*ALLCMD*/
-
- #ifdef MSDOS
- #ifdef ALLCMD
- int
- dofkey(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- int c,i,j;
- char *q, *r;
- char str[100];
-
- if(argc == 1) {
- tprintf("key num key num key num key num key num\n");
- tprintf("f1 59 sf1 84 cf1 94 af1 104 pgup 73\n");
- tprintf("f2 60 sf2 85 cf2 95 af2 105 pgdn 81\n");
- tprintf("f3 61 sf3 86 cf3 96 af3 106 home 71\n");
- tprintf("f4 62 sf4 87 cf4 97 af4 107 end 79\n");
- tprintf("f5 63 sf5 88 cf5 98 af5 108 arup 72\n");
- tprintf("f6 64 sf6 89 cf6 99 af6 109 ardn 80\n");
- tprintf("f7 65 sf7 90 cf7 100 af7 110 ar l 75\n");
- tprintf("f8 66 sf8 91 cf8 101 af8 111 ar r 77\n");
- tprintf("f9 67 sf9 92 cf9 102 af9 112 ins 82\n");
- tprintf("f10 68 sf10 93 cf10 103 af10 113 del 83\n");
- tprintf("f11 133 sf11 135 cf11 137 af11 139 stab 15\n");
- tprintf("f12 134 sf12 136 cf12 138 af12 140 cprtsc 114\n");
- tprintf("cpgup 132 cpgdn 118 chome 119 cend 117\n");
- tprintf("usage: fkey <key number> [<value> | \"string\"]\n");
- return 0;
- }
-
- c = atoi(argv[1]);
- if(c == 0 || c > 255) {
- tprintf("fkey number out of range.\n");
- return 1;
- }
-
- for(j = 0;(i = fkeys[j].fkey) != 0; j++)
- if(i == c)
- break;
-
- if(i == 0){
- tprintf("fkey number not found\n");
- return 1;
- }
-
- if(argc == 2) {
- q = fkeys[j].fvalue;
- r = str;
- if(q == NULLCHAR)
- tprintf("fkey %d has no assigned value.\n",c);
- else {
- while(*q)
- if(*q < ' ') { /* This is ASCII dependent !! */
- *r++ = '^';
- *r++ = *q++ + 0x40;
- } else
- *r++ = *q++;
- *r = '\0';
- tprintf("fkey = %s\n",str);
- }
- return 0;
- }
-
- if(argc == 3) {
- if(fkeys[j].alloced)
- fkeys[j].alloced = 0;
- else
- if(fkeys[j].fvalue != NULLCHAR)
- free(fkeys[j].fvalue);
-
- r = str;
- q = argv[2];
- while(*q){
- if(*q == '^'){ /* ^ gives control char next */
- q++;
- if(*q == '^') {
- *r++ = *q++; /* No, he wants a ^ */
- } else {
- *r++ = *q++ & 0x1f;
- }
- } else
- *r++ = *q++;
- }
- *r = '\0';
- fkeys[j].fvalue = strdup(str);
- }
- return 0;
- }
- #endif /*ALLCMD*/
- #endif /*MSDOS*/
-
- /* Install hardware interrupt handler.
- * Takes IRQ numbers from 0-7 (0-15 on AT) and maps to actual 8086/286 vectors
- * Note that bus line IRQ2 maps to IRQ9 on the AT
- */
- int
- setirq(irq,handler)
- unsigned irq;
- INTERRUPT (*handler)();
- {
- /* Set interrupt vector */
- if(irq < 8){
- #ifdef XSPAWN
- addvect(8+irq, CURRENT); /* tell XSPAWN to ignore this vector */
- #endif
- setvect(8+irq,handler);
- } else if(irq < 16){
- Isat = 1;
- #ifdef XSPAWN
- addvect(0x70 + irq - 8, CURRENT); /* tell XSPAWN to this one */
- #endif
- setvect(0x70 + irq - 8,handler);
- } else {
- return -1;
- }
- return 0;
- }
- /* Return pointer to hardware interrupt handler.
- * Takes IRQ numbers from 0-7 (0-15 on AT) and maps to actual 8086/286 vectors
- */
- INTERRUPT
- (*getirq(irq))()
- unsigned int irq;
- {
- /* Set interrupt vector */
- if(irq < 8){
- return getvect(8+irq);
- } else if(irq < 16){
- return getvect(0x70 + irq - 8);
- } else {
- return NULLVIFP;
- }
- }
- /* Disable hardware interrupt */
- int
- maskoff(irq)
- unsigned irq;
- {
- if(irq < 8){
- setbit(0x21,(char)(1<<irq));
- } else if(irq < 16){
- irq -= 8;
- setbit(0xa1,(char)(1<<irq));
- } else {
- return -1;
- }
- return 0;
- }
- /* Enable hardware interrupt */
- int
- maskon(irq)
- unsigned irq;
- {
- if(irq < 8){
- clrbit(0x21,(char)(1<<irq));
- } else if(irq < 16){
- irq -= 8;
- clrbit(0xa1,(char)(1<<irq));
- } else {
- return -1;
- }
- return 0;
- }
- /* Return 1 if specified interrupt is enabled, 0 if not, -1 if invalid */
- int
- getmask(irq)
- unsigned irq;
- {
- if(irq < 8)
- return (inportb(0x21) & (1 << irq)) ? 0 : 1;
- else if(irq < 16){
- irq -= 8;
- return (inportb(0xa1) & (1 << irq)) ? 0 : 1;
- } else
- return -1;
- }
- /* Called from assembler stub linked to BIOS interrupt 1C, called on each
- * hardware clock tick. Signal a clock tick to the timer process.
- */
- void
- ctick()
- {
- if(Watchdog)
- if(WDCurr-- == 0)
- sysreset();
- Tick++;
- #ifdef notdef
- Clock++; /* Keep system time */
- #endif
- psignal(&Tick,1);
- }
- /* Called from the timer process on every tick. NOTE! This function
- * can NOT be called at interrupt time because it calls the BIOS
- */
- void
- pctick()
- {
- long t;
- static long oldt; /* Value of bioscnt() on last call */
- static long days; /* # of times bioscnt() has rolled over */
-
- /* Update the time-since-boot */
- t = bioscnt();
-
- if(t < oldt)
- days++; /* bioscnt has rolled past midnight */
- oldt = t;
- Clock = (days * 0x1800b0) + t - Starttime;
- }
-
- /* Set bit(s) in I/O port */
- void
- setbit(port,bits)
- unsigned port;
- char bits;
- {
- outportb(port,(char)inportb(port)|bits);
- }
- /* Clear bit(s) in I/O port */
- void
- clrbit(port,bits)
- unsigned port;
- char bits;
- {
- outportb(port,(char)(inportb(port) & ~bits));
- }
- /* Set or clear selected bit(s) in I/O port */
- void
- writebit(port,mask,val)
- unsigned port;
- char mask;
- int val;
- {
- register char x;
-
- x = inportb(port);
- if(val)
- x |= mask;
- else
- x &= ~mask;
- outportb(port,x);
- }
- /* Convert a pointer to a long integer */
- long
- ptol(p)
- void *p;
- {
- long x;
-
- x = FP_OFF(p);
- #ifdef LARGEDATA
- x |= (long)FP_SEG(p) << 16;
- #endif
- return x;
- }
- void *
- ltop(l)
- long l;
- {
- register unsigned seg,offset;
-
- seg = l >> 16;
- offset = l;
- return MK_FP(seg,offset);
- }
- #ifdef notdef /* Assembler versions in pcgen.asm */
- /* Multiply a 16-bit multiplier by an arbitrary length multiplicand.
- * Product is left in place of the multiplicand, and the carry is
- * returned
- */
- int16
- longmul(multiplier,n,multiplicand)
- int16 multiplier;
- int n; /* Number of words in multiplicand[] */
- register int16 *multiplicand; /* High word is in multiplicand[0] */
- {
- register int i;
- unsigned long pc;
- int16 carry;
-
- carry = 0;
- multiplicand += n;
- for(i=n;i != 0;i--){
- multiplicand--;
- pc = carry + (unsigned long)multiplier * *multiplicand;
- *multiplicand = pc;
- carry = pc >> 16;
- }
- }
- return carry;
- }
- /* Divide a 16-bit divisor into an arbitrary length dividend using
- * long division. The quotient is returned in place of the dividend,
- * and the function returns the remainder.
- */
- int16
- longdiv(divisor,n,dividend)
- int16 divisor;
- int n; /* Number of words in dividend[] */
- register int16 *dividend; /* High word is in dividend[0] */
- {
- /* Before each division, remquot contains the 32-bit dividend for this
- * step, consisting of the 16-bit remainder from the previous division
- * in the high word plus the current 16-bit dividend word in the low
- * word.
- *
- * Immediately after the division, remquot contains the quotient
- * in the low word and the remainder in the high word (which is
- * exactly where we need it for the next division).
- */
- unsigned long remquot;
- register int i;
-
- if(divisor == 0)
- return 0; /* Avoid divide-by-zero crash */
- remquot = 0;
- for(i=0;i<n;i++,dividend++){
- remquot |= *dividend;
- if(remquot == 0)
- continue; /* Avoid unnecessary division */
- #ifdef __TURBOC__
- /* Use assembly lang routine that returns both quotient
- * and remainder, avoiding a second costly division
- */
- remquot = divrem(remquot,divisor);
- *dividend = remquot; /* Extract quotient in low word */
- remquot &= ~0xffffL; /* ... and mask it off */
- #else
- *dividend = remquot / divisor;
- remquot = (remquot % divisor) << 16;
- #endif
- }
- return remquot >> 16;
- }
- #endif
- void
- sysreset()
- {
- void (*foo) __ARGS((void));
-
- foo = MK_FP(0xffff,0); /* FFFF:0000 is hardware reset vector */
- (*foo)();
- }
-
- void stowit __ARGS((size_t index, int save, unsigned char attr));
- extern unsigned char SCREENwidth, SCREENlength;
- extern int STATLINE;
- extern struct session *ScreenOwner; /* Session currently displayed */
-
- void
- newscreen(sp)
- struct session *sp;
- {
- if(sp != NULLSESSION) {
- sp->screen = callocw(1,sizeof(struct screen));
- sp->screen->statline = STATLINE;
- }
- }
- void
- freescreen(sp)
- struct session *sp;
- {
- if(sp == NULLSESSION || sp->screen == NULLSCREEN)
- return;
- if((sp->screen->save != NULLCHAR) && sp->screen->save != (char *) 1)
- free(sp->screen->save);
- free((char *)sp->screen);
- }
-
-
- /* Save specified session screen and resume console screen */
- void
- swapscreen(old,new)
- struct session *old,*new;
- {
- struct text_info tr;
- unsigned char attr;
-
- if(old == new)
- return; /* Nothing to do */
-
- fflush(Rawterm);
- gettextinfo(&tr);
- if(old != NULLSESSION){
- /* Save old screen */
- if(old->screen->save == NULLCHAR)
- #ifndef TNOS
- old->screen->save
- = malloc(2*tr.screenheight*tr.screenwidth);
- #else
- old->screen->save = (char *) 1;
- #endif
- if(old->screen->save != NULLCHAR){
- if(old->split){
- window(1,1,SCREENwidth,SCREENlength);
- tr.winbottom = SCREENlength;
- }
- #ifndef TNOS
- gettext(tr.winleft,tr.wintop,tr.winright,
- tr.winbottom,old->screen->save);
- #else
- stowit(old->index, 1, 0); // save it
- #endif
- }
- old->screen->row = tr.cury;
- old->screen->col = tr.curx;
- old->screen->attr = tr.attribute;
- }
- if(new != NULLSESSION){
- /* Load new screen */
- if(new->screen->save != NULLCHAR){
- if(new->split){
- window(1,1,SCREENwidth,SCREENlength - 2);
- #ifndef TNOS
- clrscr();
- #endif
- } else {
- window(1,1,SCREENwidth,SCREENlength);
- #ifndef TNOS
- clrscr();
- #endif
- }
- #ifndef TNOS
- puttext(tr.winleft,tr.wintop,tr.winright,
- tr.winbottom,new->screen->save);
- /* Free the memory (saves 4K on a continuous basis) */
- free(new->screen->save);
- #else
- setscreens ((new->screen->attr >> 4) & 0x07, new->screen->attr & 0x0f, 0);
- stowit (new->index, 0, new->screen->attr); // retrieve it
- new->screen->attr &= 0x7f; // remove color change bit
- #endif
- // if (STATLINE && (Current == Command))
- window (1,1 + new->screen->statline,SCREENwidth,SCREENlength - (new->split * 2));
- gotoxy(new->screen->col,new->screen->row);
- textattr (new->screen->attr);
- new->screen->save = NULLCHAR;
- } else {
- window(1,1,SCREENwidth,SCREENlength);
- clrscr(); /* Start with a fresh slate */
- if(new->split){
- new->tsavex = 1;
- new->tsavey = 1;
- new->bsavex = 1;
- new->bsavey = SCREENlength - 1;
- window(1,SCREENlength - 1,SCREENwidth,SCREENlength);
- gettextinfo(&tr);
- attr = ((tr.attribute & 0x0f) << 4) + ((tr.attribute & 0x70) >> 4);
- textattr (attr);
- clrscr ();
- cputs("_\b");
- window(1,1 + new->screen->statline,SCREENwidth,SCREENlength - 2 - new->screen->statline);
- textattr (tr.attribute);
- }
- else
- window(1,1 + new->screen->statline,SCREENwidth,SCREENlength - new->screen->statline);
- // if (STATLINE)
- // displayStatLine (-1);
- }
- }
- ScreenOwner = new;
- displayStatLine (0, 1);
- alert(Display,1); /* Wake him up */
- }
-
- void
- display(i,v1,v2)
- int i;
- void *v1;
- void *v2;
- {
- int c;
- struct session *sp;
-
- /* This is very tricky code. Because the value of "Current" can
- * change any time we do a pwait, we have to be careful to detect
- * any change and go back and start again.
- */
- for(;;){
- sp = Current;
-
- if(sp->morewait){
- pwait(&sp->row);
- if(sp != Current || sp->row <= 0){
- /* Current changed value, or the user
- * hasn't really hit a key
- */
- continue;
- }
- /* Erase the prompt */
- fprintf(Rawterm,"\b\b\b\b\b\b\b\b \b\b\b\b\b\b\b\b");
- rflush ();
- }
- sp->morewait = 0;
- if((c = rrecvchar(sp->output)) == -1){
- /* the alert() in swapscreen will cause this to
- * return -1 when current changes
- */
- pwait(NULL); /* Prevent a nasty loop */
- continue;
- }
- #ifdef SCREENSAVER
- sskick ();
- #endif
- if(sp->split){
- if(c == 0x0a){
- cputs(Eol);
- clreol();
- } else
- putch(c);
- } else {
- putc(c,Rawterm);
- }
- /* Fix by Ron Murray, vk6zjm */
- if(sp->record != NULLFILE) /* Don't save CR if ascii mode */
- if (c != '\r' || sockmode(sp->output, -1) != SOCK_ASCII)
- putc(c,sp->record);
- #ifdef notdef
- if(sp->record != NULLFILE)
- putc(c,sp->record);
- #endif
- if(sp->flowmode && c == '\n' && --sp->row <= 0){
- fprintf(Rawterm,"--More--");
- sp->morewait = 1;
- }
- }
- }
- /* Return time since startup in milliseconds. If the system has an
- * 8254 clock chip (standard on ATs and up) then resolution is improved
- * below 55 ms (the clock tick interval) by reading back the instantaneous
- * value of the counter and combining it with the global clock tick counter.
- * Otherwise 55 ms resolution is provided.
- *
- * Reading the 8254 is a bit tricky since a tick could occur asynchronously
- * between the two reads. The tick counter is examined before and after the
- * hardware counter is read. If the tick counter changes, try again.
- * Note: the hardware counter counts down from 65536.
- */
- int32
- msclock()
- {
- int32 hi;
- int16 lo;
- int16 count[4]; /* extended (48-bit) counter of timer clocks */
-
- if(!Isat)
- return Clock * MSPTICK;
-
- do {
- hi = Clock + Tick;
- lo = clockbits();
- } while(hi != Clock + Tick); /* Make sure a tick didn't just occur */
-
- count[0] = 0;
- count[1] = hi >> 16;
- count[2] = hi;
- count[3] = -lo;
- longmul(11,4,count); /* The ratio 11/13125 is exact */
- longdiv(13125,4,count);
- return ((long)count[2] << 16) + count[3];
- }
- /* Return clock in seconds */
- int32
- secclock()
- {
- int32 hi;
- int16 lo;
- int16 count[4]; /* extended (48-bit) counter of timer clocks */
-
- if(!Isat)
- return Clock * MSPTICK / 1000L;
-
- do {
- hi = Clock + Tick;
- lo = clockbits();
- } while(hi != Clock + Tick); /* Make sure a tick didn't just occur */
-
- count[0] = 0;
- count[1] = hi >> 16;
- count[2] = hi;
- count[3] = -lo;
- longmul(11,4,count); /* The ratio 11/13125 is exact */
- longdiv(13125,4,count);
- longdiv(1000,4,count);
- return ((long)count[2] << 16) + count[3];
- }
-
- int
- doisat(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- return setbool(&Isat,"AT/386 mode",argc,argv);
- }
-
- /* Directly read BIOS count of time ticks. This is used instead of
- * calling biostime(0,0L). The latter calls BIOS INT 1A, AH=0,
- * wich resets the midnight overflow flag, losing days on the clock.
- */
- long
- bioscnt()
- {
- int i_state;
- long rval;
-
- i_state = dirps();
- rval = * (long DFAR *)MK_FP(0x40,0x6c);
- restore(i_state);
- return rval;
- }
-
- /* same as getenv(), but return "" instead of NULL when it does not exist */
- char *getnenv (name)
- char *name;
- {
- char *rv;
-
- if ((rv = getenv(name)) == NULL)
- rv = ""; /* NULL replaced by "" */
-
- return rv;
- }
-